Skip to content

Preserve Zod v4 schemas when cloning custom tool definitions - #1339

Closed
alexander-alex-roy wants to merge 1 commit into
CodebuffAI:mainfrom
alexander-alex-roy:fix/mcp-tool-params-lost-to-clonedeep
Closed

alexander-alex-roy wants to merge 1 commit into
CodebuffAI:mainfrom
alexander-alex-roy:fix/mcp-tool-params-lost-to-clonedeep

Conversation

@alexander-alex-roy

Copy link
Copy Markdown

Fixes #1306.

What

MCP tool parameters were arriving at MCP servers as {}. The cause was lodash.cloneDeep applied to custom tool definitions in three places: getToolSet (packages/agent-runtime/src/tools/prompts.ts), additionalToolDefinitions (packages/agent-runtime/src/run-agent-step.ts), and executeCustomToolCall (packages/agent-runtime/src/tools/tool-executor.ts).

Why

Zod v4 keeps its engine in the non-enumerable _zod field, which cloneDeep does not copy. The cloned schema keeps a copied safeParse, so ensureZodSchema still accepts it as a Zod schema, but any z.toJSONSchema() call then crashes on the missing _zod (schema._zod.def is undefined — even reading .description throws via schema._zod.parent). The tool's params collapse to {} or getToolSet throws outright. I reproduced this end-to-end through getToolSet before fixing.

Change

  • Added exported cloneToolDefinition / cloneCustomToolDefinitions helpers in packages/agent-runtime/src/tools/prompts.ts: genuine Zod schemas (instanceof z.ZodType) are kept by reference since they are treated as immutable downstream; plain JSON Schema objects and remaining fields are still deep-cloned.
  • Replaced the three cloneDeep call sites with the Zod-aware helpers. No backend, billing, or deployment paths touched.
  • Added three regression tests to packages/agent-runtime/src/__tests__/prompts-schema-handling.test.ts: schema identity and _zod preserved, JSON-schema defs still deep-cloned without aliasing, and end-to-end getToolSet serving query/max_results after the clone path.

Verification

  • prompts-schema-handling.test.ts: 19/20 pass, including all 3 new tests. The single failure (allOf representation) is pre-existing on clean main. The fix also repaired a second pre-existing failure (getToolSet handles custom tools with problematic schemas).
  • Neighbor suites (run-agent-step-tools, to-token-count-input-schema, tool-validation-error, loop-agent-steps): 70/70 pass.
  • Package typecheck shows no errors in the touched files.

@alexander-alex-roy
alexander-alex-roy deleted the fix/mcp-tool-params-lost-to-clonedeep branch September 12, 2026 18:35
@dvelm

dvelm commented Sep 14, 2026

Copy link
Copy Markdown

no

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

2 participants